#include <Arduino.h>
#include "RFIDNFCLib.h"
#include "HardwareSerial.h"

bool RFIDNFCLib::StartRFIDNFC(void){
	Serial.print("<--\tStartRFIDNFC: { ");
	// Just to start syncronization
	Serial1.print("                ");
    
	memset(dataTX, 0x00, 35);
	dataTX[0] = 0x02; // Length
	lengthCheckSum(dataTX); // Length Checksum
	dataTX[2] = 0xD4; // CODE
	dataTX[3] = 0x02; //TFI
	checkSum(dataTX); //0x2A; //Checksum   
	Serial.print("firmware : ");
	sendTX(dataTX , 5 , 17);
	

	for (int i = 11; i < (15) ; i++){
		Serial.print(dataRX[i], HEX);
		Serial.print(" ");
	}

	//Serial.print("result: "); Serial.print((uint16_t)msg -> result, HEX);
    Serial.println(" }");
}

bool RFIDNFCLib::ConfigureSAM(void){
	Serial.println("<--\tConfigureSAM");
	Serial1.print("               ");

	dataTX[0] = 0x05; //Length
	lengthCheckSum(dataTX); // Length Checksum
	dataTX[2] = 0xD4;
	dataTX[3] = 0x14;
	dataTX[4] = 0x01; // Normal mode
	dataTX[5] = 0x14; // TimeOUT
	dataTX[6] = 0x00; // IRQ
	dataTX[7] = 0x00; // Clean checkSum position
	checkSum(dataTX);

	sendTX(dataTX , 8, 13);
}

//!The goal of this command is to detect as many targets (maximum MaxTg)
// as possible in passive mode.
uint8_t RFIDNFCLib::DetectTag(void){
	Serial1.flush();

	dataTX[0] = 0x04; // Length
	lengthCheckSum(dataTX); // Length Checksum
	dataTX[2] = 0xD4;
	dataTX[3] = 0x4A; // Code
	dataTX[4] = 0x01; //MaxTarget
	dataTX[5] = 0x00; //BaudRate = 106Kbps
	dataTX[6] = 0x00; // Clear checkSum position
	checkSum(dataTX); 

	sendTX(dataTX , 7 ,23);

	for (int i = 17; i < (21) ; i++){
		_UID[i-17] = dataRX[i];
	}

	ATQ[0] = dataRX[13];
	ATQ[1] = dataRX[14];

	if ((dataRX[9]== 0xD5) & (dataRX[10] == 0x4B) & (dataRX[11] == 0x01)) {
		return 0;
	} else {
		return 1;
	}
}

void RFIDNFCLib::PrintUIDTagDetected(void){
	Serial.print("<--\tPrintUIDTagDetected: { ");
	Serial.print("UID : ");
	for (int i = 0; i < (4) ; i ++){
		Serial.print(_UID[i], HEX);
		Serial.print(" ");
	}
	Serial.println(" }");
}

void RFIDNFCLib::sendTX(uint8_t *_dataTX, uint8_t length, uint8_t outLength){
	Serial1.write((byte)0x00);
	Serial1.write((byte)0x00);
	Serial1.write((byte)0xFF); 

	for (int i = 0; i < length; i++) {
		Serial1.write((byte)_dataTX[i]);
	}

	Serial1.write((byte)0x00);
	Serial1.flush();
	getACK();
	waitResponse();// Receive response
	getData(outLength);
}

//!Wait for ACK response and stores it in the dataRX buffer
void RFIDNFCLib::getACK(void){
	delay(5);
	waitResponse();
	for (int i = 0; i < 5 ; i++) {
		dataRX[i] = Serial1.read();
	}
}
//**********************************************************************
//!Wait the response of the module
void RFIDNFCLib::waitResponse(void){
	int val = 0xFF;
	int cont = 0x00;

	while(val != 0x00) { //Wait for 0x00 response
		val = Serial1.read();
		delay(5);
		cont ++;
	}
}

void RFIDNFCLib::getData(uint8_t outLength){
	for (int i=5; i < outLength; i++) {
		dataRX[i] = Serial1.read();//read data from the module.
	}
}

void RFIDNFCLib::checkSum(uint8_t *_dataTX){
	for (int i = 0; i < _dataTX[0] ; i++){
		_dataTX[_dataTX[0] + 2] += _dataTX[i + 2];
	}
	byte(_dataTX[_dataTX[0] + 2]= - _dataTX[_dataTX[0] + 2]);
}
//**********************************************************************
//!Calculates the length checksum and sotres it in the buffer.
uint8_t RFIDNFCLib::lengthCheckSum(uint8_t *_dataTX){
	_dataTX[1] = byte(0x100 - _dataTX[0]);
}

